Skip to content

fix(providerplatforms): allowlist order_by in OrderClause (EN-229) - #4

Merged
CK-7vn merged 1 commit into
mainfrom
EN-229-sql-injection-order-by
Nov 9, 2026
Merged

CK-7vn merged 1 commit into
mainfrom
EN-229-sql-injection-order-by

Conversation

@CK-7vn

@CK-7vn CK-7vn commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

Description of the change

OrderClause returned a bare order_by when no direction was sent and coerced a bad direction to desc, but it never checked the column. It now takes the columns a query may sort by and falls back to the query's default for anything else, matching core's OrderClause (UnlockedLabs/unlocked-core#1294).

  • queryContext.OrderClause(fallback string, allowed ...string) in http.go returns <order_by> <dir> only when order_by is in allowed and the direction is asc or desc (case-insensitive; asc when absent). Anything else returns fallback.
  • getOutcomesForUser (store.go) passes created_at and type as its allowlist, replacing the check that rewrote args.OrderBy.
  • Tests: new order_clause_test.go covers the direction and allowlist cases, hostile order_by/order on outcomes, and the user courses and catalog sorts (already safe through validOrder and the field map; characterization tests). The old coerce-to-desc assertion in http_test.go is removed, since a bad direction now falls back instead.

Behavior change: outcomes with no order_by now default to outcomes.created_at DESC instead of created_at ascending. Nothing in the frontend calls this endpoint.

EN-229 also needs UnlockedLabs/unlocked-core#1294 and UnlockedLabs/unlocked-programs#5.

Pre-Submission PR Checklist

  • No debug/console/fmt.Println statements

  • Unnecessary development comments removed

  • All acceptance criteria verified

  • Functions according to ticket specifications

  • Tested manually where applicable (covered by automated tests only; no manual or Postgres run)

  • Branch rebased with latest main

  • No business logic exists within the database layer

  • DB migrations (if any) are backward-compatible and online-safe (no migrations)

  • PR title and every commit are conventional commits (feat:, fix:, docs:...); a squash merge lands under the PR title, and both become the changelog

  • Related issues: EN-229

Release

  • Changelog type: fix
  • Breaking change?: no

OrderClause returned a bare order_by when no direction was sent and coerced a bad direction to desc. It now takes the columns a query may sort by and falls back to the query's default for anything else, matching core and programs.
@CK-7vn
CK-7vn requested a review from a team as a code owner November 9, 2026 19:10
@CK-7vn
CK-7vn requested review from corypride and removed request for a team November 9, 2026 19:10
@carddev81
carddev81 requested review from carddev81 and removed request for corypride November 9, 2026 21:07

@carddev81 carddev81 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CK-7vn , the code here looks good. OrderClause now matches core, getOutcomesForUser is the only caller and passes created_at and type, and the courses and catalog sorts were already safe through validOrder and the field map. The new tests cover them anyway. go vet and go test ./... pass at 944d05b.

One thing to fix:

The PR description is garbled. Parts of it got cut off or run together, for example "OrderClause(fallback string, all/providerplatforms/http.go", "andesc", "passes crenger pre-resets" and "http_test.go catalog sorts`". There's also an empty "Description of the change" heading at the top and a second one further down. Please rewrite it so a reviewer can read it.

While you're in there, change "matching core and programs": the Programs fix isn't in any open PR right now (see my note on core #1294). Also, outcomes with no order_by now default to outcomes.created_at DESC instead of the old created_at ascending. Nothing in the frontend calls this endpoint, so it's fine, but it's worth a line in the description.

EN-229 can't close from this PR alone. It also needs core #1294 and a new unlocked-programs PR merged (details are on #1294).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants